#include "timer.h"
#include "util.h"
#include <memory>

namespace framework
{

//取消定时器
bool Timer::cancel()
{
    TimerManager::RWMutexType::WriteLock lock(m_manager->m_mutex);
    if(m_cb)
    {
        m_cb = nullptr;
        auto it = m_manager->m_timers.find(shared_from_this());
        m_manager->m_timers.erase(it);
        return true;
    }
    return false;
}

//刷新设置定时器的执行时间
bool Timer::refresh()
{
    TimerManager::RWMutexType::WriteLock lock(m_manager->m_mutex);
    if(!m_cb)
    {
        return false;
    }
    auto it = m_manager->m_timers.find(shared_from_this());
    if(it == m_manager->m_timers.end())
    {
        return false;
    }

    m_manager->m_timers.erase(it);
    m_next = framework::GetCurrentMS() + m_ms;
    m_manager->m_timers.insert(shared_from_this());

    return true;
}

//重置定时器时间
//ms 定时器执行时间间隔（毫秒）
//from_now 是否从当前时间开始计算
bool Timer::reset(uint64_t ms, bool from_now)
{
    if(ms == m_ms && !from_now)
    {
        return true;
    }
    TimerManager::RWMutexType::WriteLock lock(m_manager->m_mutex);

    if(!m_cb)
    {
        return false;
    }
    auto it = m_manager->m_timers.find(shared_from_this());
    if(it == m_manager->m_timers.end())
    {
        return false;
    }

    m_manager->m_timers.erase(it);
    uint64_t start = 0;
    if(from_now)
    {
        start = framework::GetCurrentMS();
    }
    else
    {
        //回到上一次定时的时间
        start = m_next - m_ms;
    }
    m_ms = ms;
    m_next = start + m_ms;
    m_manager->addTimer(shared_from_this(), lock);
    
    return true;
}

//构造函数，写在private中，只能通过TimerManager类来构造Timer
//ms: 定时器执行时间间隔
//cb: 回调函数
//recurring: 是否循环
//manager: 定时器管理器
Timer::Timer(bool recurring, uint64_t ms, TimerManager* manager, std::function<void()> cb)
    :m_recurring(recurring)
    ,m_ms(ms)
    ,m_manager(manager)
    ,m_cb(cb)
{
    m_next = framework::GetCurrentMS() + ms;
}

//构造函数
//next 执行的时间戳（毫秒）
Timer::Timer(uint64_t next):m_next(next) {}

//比较定时器的智能指针的大小 按照定时器的执行时间比较
//set容器需要一个小于号的比较器
bool Timer::Comparator::operator()(const Timer::ptr& lhs, const Timer::ptr& rhs) const
{
    if(!lhs && !rhs)
    {
        return false;
    }

    if(!lhs)
    {
        return true;
    }
    if(!rhs)
    {
        return false;
    }

    if(lhs->m_next < rhs->m_next)
    {
        return true;
    }
    if(rhs->m_next < lhs->m_next)
    {
        return false;
    }

    return lhs.get() < rhs.get();

    return true;
}


//----------------------------------------------------------------------


TimerManager::TimerManager()
{
    m_previouseTime = framework::GetCurrentMS();
}

TimerManager::~TimerManager()
{

}

//添加定时器
//ms 定时器执行的时间间隔
//cb 定时器回调函数
//recurring 是否循环定时器
Timer::ptr TimerManager::addTimer(uint64_t ms, std::function<void()> cb, bool recurring)
{
    Timer::ptr timer(new Timer(recurring, ms, this, cb));
    RWMutexType::WriteLock lock(m_mutex);
    addTimer(timer, lock);
    return timer;
}


static void OnTimer(std::weak_ptr<void> weak_cond, std::function<void()> cb)
{
    std::shared_ptr<void> tmp = weak_cond.lock(); //weak_ptr::lock()为返回shared_ptr的指针
    if(tmp)
    {
        cb();
    }
}

//添加条件定时器
//ms 定时器执行的时间间隔
//cb 定时器回调函数
//weak_cond 条件
//recurring 是否循环定时器
Timer::ptr TimerManager::addConditionTimer(uint64_t ms, std::function<void()> cb,  std::weak_ptr<void> weak_cond, bool recurring)
{
    return addTimer(ms, std::bind(&OnTimer, weak_cond, cb), recurring);
}

//返回到最近一个定时器执行的时间间隔（毫秒）
uint64_t TimerManager::getNextTimer()
{
    RWMutexType::ReadLock lock(m_mutex);
    m_tickled = false;
    if(m_timers.empty())
    {
        return ~0ull;
    }

    //获取到m_timers中第一个元素
    const Timer::ptr& next = *m_timers.begin();
    uint64_t now_ms = framework::GetCurrentMS(); //获取当前时间
    if(now_ms >= next->m_next)
    {
        return 0;
    }
    else
    {
        return next->m_next - now_ms;
    }
}

//获取需要执行的定时器回调函数列表
//cbs 回调函数数组
void TimerManager::listExpiredCb(std::vector<std::function<void()>>& cbs)
{
    uint64_t now_ms = framework::GetCurrentMS();

    //存放已经超时定时器的数组
    std::vector<Timer::ptr> expired;

    {
        RWMutexType::ReadLock lock(m_mutex);
        if(m_timers.empty())
        {
            return;
        }
    }

    RWMutexType::WriteLock lock(m_mutex);
    if(m_timers.empty())
    {
        return;
    }

    //检测服务器时间是否被调后了
    bool rollover = detectClockRollover(now_ms);
    if(!rollover && (*m_timers.begin())->m_next > now_ms)
    {
        //如果时间没有调后，并且当前没有需要执行的定时器
        return;
    }

    Timer::ptr now_timer(new Timer(now_ms));
    auto it = rollover ? m_timers.end() : m_timers.lower_bound(now_timer);
    while(it != m_timers.end() && (*it)->m_next == now_ms)
    {
        ++it;
    }
    expired.insert(expired.begin(), m_timers.begin(), it);
    m_timers.erase(m_timers.begin(), it);

    cbs.reserve(expired.size());
    for(auto& timer: expired)
    {
        cbs.push_back(timer->m_cb);
        //如果是循环定时器
        if(timer->m_recurring)
        {
            timer->m_next = now_ms + timer->m_ms;
            m_timers.insert(timer);
        }
        else
        {
            //防止回调函数中有智能指针，引用计数不会变化
            timer->m_cb = nullptr; 
        }
    }

}

//是否有定时器
bool TimerManager::hasTimer()
{
    RWMutexType::ReadLock lock(m_mutex);
    return !m_timers.empty();
}

//将定时器添加到管理器中
void TimerManager::addTimer(Timer::ptr val, RWMutexType::WriteLock& lock)
{
    //插入数据并返回插入数据的位置
    auto it = m_timers.insert(val).first;

    //是否插到了定时器的首部
    bool at_font = (it == m_timers.begin()) && !m_tickled;

    if(at_font)
    {
        m_tickled = true;
    }

    lock.unlock();

    if(at_font)
    {
        //因为有一个最小等待时间的任务添加进来了，可能有某些任务要重新设置等待时间
        onTimerInsertedAtFront();
    }

}

//检测服务器时间是否被调后了
bool TimerManager::detectClockRollover(uint64_t now_ms)
{
    bool rollover = false;
    //现在的时间小于上次执行时间小一小时
    if(now_ms < m_previouseTime && now_ms < (m_previouseTime - 60*60*1000))
    {
        rollover = true;
    }
    m_previouseTime = now_ms;
    return rollover;

    return true;
}

}

